# -*- coding: utf-8 -*-
# kate: space-indent on; tab-width 4; indent-width 4; indent-mode python; backspace-indents; encoding utf-8; line-numbers on; remove-trailing-space on;
#   Copyright 2010 Thomas Olsen <tanghus@gmail.com>
#
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU Library General Public License as
#   published by the Free Software Foundation; either version 2 or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#
#   GNU General Public License for more details
#
#
#   You should have received a copy of the GNU Library General Public
#   License along with this program; if not, write to the
#   Free Software Foundation, Inc.,
#
#   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
#
from PyQt4 import QtCore
from PyQt4.QtCore import * # Qt, QVariant, QSize, SIGNAL
from PyQt4.QtGui import *
from PyKDE4.kdecore import i18n, KUrl, KGlobal
from PyKDE4.kdeui import KIcon
from PyKDE4.plasma import Plasma
from PyKDE4.kio import *
from xml.dom.minidom import parseString
from urllib import quote
import copy, datetime
from LastFMEvent import LastFMEvent
from webservices import webservices

class LastFMEventList(QGraphicsWidget): #, QGraphicsWidget):
    def __init__(self, parent):
        QGraphicsWidget.__init__(self)
        self.applet = parent
        self.events = []
        self.layout_tainted = True
        self.layout = QGraphicsLinearLayout(Qt.Vertical, self)
        self.layout.setSpacing(4)
        self.setLayout(self.layout)

    def count(self):
        return len(self.events)

    @QtCore.pyqtSlot(name="clear")
    def clear(self):
        print "Clearing %i events." % self.count()
        events = copy.copy(self.events)
        for event in events:
            self._removeItem(event, False)
        self.events = []
        self._update()

    @QtCore.pyqtSlot(name="clearExpired")
    def clearExpired(self):
        #print "clearExpired"
        events = copy.copy(self.events)
        for event in events:
            # if the start date/time has been passed by 5 hrs.
            #print event.getTitle()
            #print "Is %s < %s?" % (str(event.startDate()+ datetime.timedelta(hours=5)), str(datetime.datetime.now())) #+ datetime.timedelta(hours=5)))
            if (event.startDate()+ datetime.timedelta(hours=5)) < (datetime.datetime.now()): #+ datetime.timedelta(hours=5)):
                #print "Apparently so..."
                self._removeItem(event, False)
        self._update()

    def addItem(self, event):
        # Don't add it if it has started >= 5 hrs. ago
        if (event.startDate()+ datetime.timedelta(hours=5)) < (datetime.datetime.now()): #+ datetime.timedelta(hours=5)):
            #print "Skip adding %s: %s" % (event.getTitle(), event.startDate())
            return
        for e in self.events:
            if e.getId() == event.getId():
                event.deleteLater()
                return
        self.events.append(event)
        self.layout.addItem(event)
        self.layout_tainted = True
        event.open_url.connect(self.applet.open_url)

    def _update(self):
        if not self.layout_tainted:
            return
        self.resize(self.effectiveSizeHint(Qt.PreferredSize))
        self.layout.invalidate()
        self.layout.activate()

    def _removeItem(self, event, update=True):
        #print u"LastFMEventList::_removeItem - %s" % str(event.getTitle())
        self.layout.removeItem(event)
        self.events.remove(event)
        event.deleteLater()
        #del event # Probably not neccesary
        if update:
            self._update()
        else:
            self.layout_tainted = True

    def findById(self, eid):
        for event in self.events:
            if eid == event.getId():
                return event
        return None # Good to be explicit ;-)

    def removeItem(self, event):
        if type(event) is int:
            eventobj = self.findById(event)
            if eventobj:
                self._removeItem(eventobj)
            else:
                raise AttributeError, "LastFMEvent '%i' not found!" % event
        elif isinstance(event, LastFMEvent):
            self._removeItem(event)

class LastFMEvents(QGraphicsWidget):
    def __init__(self, parent):
        QGraphicsWidget.__init__(self)
        self.applet = parent
        print "LastFMEvents " + str(self.applet)

    def init(self):
        print "Country: " + str(KGlobal.locale().countryCodeToName(KGlobal.locale().country()))
        self.timer = None
        self.jobs = {}
        # FIXME: Reading the config should be done in the applet class.
        self.country = self.applet.cfg.readEntry("country", QString("Denmark")).toString()
        self.metro = self.applet.cfg.readEntry("metro", QString("Copenhagen")).toString()
        self.update_interval = self.applet.cfg.readEntry("update_interval", QVariant(12)).toInt()[0] # why does this return a tuple?
        self.distance = self.applet.cfg.readEntry("distance", QVariant(50)).toInt()[0]

        # Create controls
        self.title = Plasma.Label()
        self.title.setText(self.applet.metadata.name())
        self.title.setAlignment(Qt.AlignCenter)
        f = self.title.nativeWidget().font()
        f.setBold(True)
        self.title.nativeWidget().setFont(f)
        self.scroll = Plasma.ScrollWidget(self)
        self.events = LastFMEventList(self)
        self.scroll.setWidget(self.events)

        #self.btn_update = Plasma.PushButton(self)
        #self.btn_update.setText(i18n('Update'))
        #self.btn_update.clicked.connect(self.update_events)

        #self.btn_clear = Plasma.PushButton(self)
        #self.btn_clear.setText(i18n('Clear'))
        #self.btn_clear.clicked.connect(self.events.clear)

        # Layout
        self.layout = QGraphicsLinearLayout(Qt.Vertical, self)
        self.layout.setSpacing(1)
        #self.layout.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))
        self.layout.addItem(self.title)
        self.layout.addItem(self.scroll)
        #self.layout.addItem(self.btn_update)
        #self.layout.addItem(self.btn_clear)

        self.setLayout(self.layout)

        self.setMinimumWidth(260)
        self.setMinimumHeight(500)
        if self.update_interval > 0:
            self.start_timer()
        else:
            self.update_events()

    def start_timer(self):
        print "CurrencyConverter::start_timer '%s'" % self.update_interval
        if not self.timer:
            self.timer = QTimer(self)
        else:
            self.timer.stop()
        if self.update_interval > 0:
            self.timer.setInterval(1000*60*60*self.update_interval)
            self.timer.timeout.connect(self.update_events)
            self.timer.start()
            self.update_events()

    def clear(self):
        self.events.clear()

    @pyqtSlot(name="update_events")
    def update_events(self):
        if not self.applet.nwmon.connected():
            return
        print 'LastFMEvents: update_events'
        self.events.clearExpired()
        #if self.swapping or not self.applet.nwmon.connected():
            #return
        self.location = quote("%s,%s" % (str(self.metro), str(self.country)))
        key = webservices["lastfm"]["key"]
        self.source = "http://ws.audioscrobbler.com/2.0/?method=geo.getevents&location=%s&distance=%d&api_key=%s" % (
                                                                            self.location, self.distance, key)
        print self.source
        self.applet.setBusy(True)
        #self.detect_button.setEnabled(False)
        job = KIO.get(KUrl(self.source), KIO.NoReload, KIO.HideProgressInfo)
        print "KIO Job: " + str(job)
        self.jobs[job] = {}
        self.jobs[job]['idx'] = 0
        self.jobs[job]['data'] = ""
        #self.jobs[job]['mimetype'] = ""
        job.data.connect(self.job_received)
        #job.mimetype.connect(self.job_mimetype)
        try:
            # This should work from KDE SC 4.5
            job.result.connect(self.job_done)
        except AttributeError as (errno, strerror):
            print "I/O error({0}): {1}".format(errno, strerror)
            debug("missing new-style support for KIO.Job.result")
            QObject.connect(job, SIGNAL("result( KJob *)"), self.detect_job_done)

    def job_received(self, job, data):
        if self.jobs.has_key(job) and data: #len(data) > 0:
            print "job_received\n"
            self.jobs[job]['data'] += str(data)

    def job_done(self, job):
        print("job_done")
        if self.jobs.has_key(job):
            #data = unicode(self.jobs[job]['data'], encoding='utf-8')
            data = self.jobs[job]['data']
            #print data
            dom = parseString(data)
            events = dom.getElementsByTagName('event')
            for item in events:
                print "ID: " + LastFMEvent.getGetIdFromDom(LastFMEvent, item)
                event = LastFMEvent(item, self.applet)
                self.events.addItem(event)
            self.events._update()
            del self.jobs[job]
        else:
            debug("Job went AWOL?!")

        self.applet.setBusy(False)

    def open_url(self, url):
        # Open last.fm evvent in browser
        #print u"LastFMEvents::open_url: " + url
        if not self.applet.nwmon.connected():
            return
        QDesktopServices.openUrl(QUrl(url))